import React from "react";
import { Select, Spin, List, Avatar, Button, SelectProps } from "antd";
import debounce from "lodash/debounce";
import api from "src/http/api";
import { UserProps } from "src/utils/interface";
const { useState, useEffect, useRef } = React;
interface DebounceSelectProps<ValueType = any>
  extends Omit<SelectProps<ValueType>, "string" | "options" | "children"> {
  fetchOptions: (search: string) => Promise<ValueType[]>;
  debounceTimeout?: number;
}

function DebounceSelect<
  ValueType extends {
    key?: string;
    username: string;
    email: string;
    avatar: string;
  } = any
>({ fetchOptions, debounceTimeout, ...props }: DebounceSelectProps) {
  const [fetching, setFetching] = useState(false);
  const [options, setOptions] = useState<ValueType[]>([]);
  const fetchRef = useRef(0);

  const debounceFetcher = React.useMemo(() => {
    const loadOptions = (value: string) => {
      fetchRef.current += 1;
      const fetchId = fetchRef.current;
      setOptions([]);
      setFetching(true);

      fetchOptions(value).then((newOptions) => {
        if (fetchId !== fetchRef.current) {
          return;
        }

        setOptions(newOptions);
        setFetching(false);
      });
    };

    return debounce(loadOptions, debounceTimeout);
  }, [fetchOptions, debounceTimeout]);

  return (
    <Select
      showSearch
      labelInValue
      filterOption={false}
      onSearch={debounceFetcher}
      notFoundContent={fetching ? <Spin size="small" /> : null}
      optionLabelProp="value"
      mode="multiple"
      {...props}
    >
      {options.map((item) => (
        <Select.Option value={item.username} key={item.username}>
          <List.Item.Meta
            avatar={<Avatar src={item.avatar} />}
            title={<Button type="link">{item.username}</Button>}
            description={item.email}
          />
        </Select.Option>
      ))}
    </Select>
  );
}

interface Props {
  debounceTimeout?: number;
  placeholder?: string;
  value?: string[];
  onChange: (value: any) => void;
}

interface OptionType {
  label: string;
  value: string;
  key?: string;
}

export const OwnersSelect: React.FC<Props> = (props) => {
  const [value, setValue] = useState<OptionType[]>([]);

  const fetchUSerList = async (query: string): Promise<UserProps[]> => {
    return new Promise((resolve) => {
      api.getUsers({ query }).then((res: any) => {
        resolve(res.data);
      });
    });
  };

  useEffect(() => {
    if (!props.value || props.value.length === 0) return;
    const initValue = props.value.map((item) => ({
      label: item,
      value: item,
      key: item,
    }));
    setValue(initValue);
  }, [props.value]);

  return (
    <DebounceSelect
      {...props}
      value={value}
      placeholder={props.placeholder || "Select Users"}
      debounceTimeout={props.debounceTimeout || 800}
      fetchOptions={fetchUSerList}
      onChange={(newValue) => {
        props.onChange(newValue.map((item: any) => item.value));
        setValue(newValue);
      }}
      style={{ width: "100%" }}
    />
  );
};

export const OwnerSelect: React.FC<Props> = (props) => {
  const [value, setValue] = useState<OptionType>();

  const fetchUSerList = async (query: string): Promise<UserProps[]> => {
    return new Promise((resolve) => {
      api.getUsers({ query }).then((res: any) => {
        resolve(res.data);
      });
    });
  };

  return (
    <DebounceSelect
      {...props}
      value={value}
      mode={undefined}
      placeholder={props.placeholder || "Select User"}
      debounceTimeout={props.debounceTimeout || 800}
      fetchOptions={fetchUSerList}
      onChange={(newValue) => {
        props.onChange(newValue.value);
        setValue(newValue);
      }}
      style={{ width: "100%" }}
    />
  );
};

export default OwnersSelect;
